#include "DeviceManagerClient.h"
#include "esp_wifi.h"
#include "esp_event.h"
#include "esp_log.h"
#include "esp_err.h"
#include "esp_netif.h"
#include "nvs_flash.h"
#include "driver/gpio.h"
#include "utils/utils.h"
#include <string.h>
#include <stdlib.h>
#include "manager.h"
#include "DeviceManager/DeviceManagerDefine.h"

static const char *TAG = "ESP_NOW_EX";

struct DeviceManagerClient
{
     uint8_t self_mac[6]; // 本机 MAC
     uint8_t broadcastAddress[6];
     NetConfig netConfig;
     recv_net_config_event_callback *recv_net_config_event_callback_t;

     TaskHandle_t ask_info_when_start_task_handle;
};

// 设置 获取网络配置信息的回调
void DeviceManagerClient_set_recv_netConfig_callback(DeviceManagerClient *handle, recv_net_config_event_callback cb)
{
     if (handle)
          handle->recv_net_config_event_callback_t = cb;
}

// ------------------------内部函数定义------------------------
void add_broadcast_peer(DeviceManagerClient *handle, uint8_t peerAddress[]);
void sub_device_ASK_NET_INFO(DeviceManagerClient *handle, uint8_t peerAddress[6]);
void handle_ASK_DEVICE_INFO(DeviceManagerClient *handle, uint8_t peerAddress[6], const char *msgId);
void handle_BROADCAST_NET_INFO(DeviceManagerClient *handle, cJSON *root);
void handle_BROADCAST_ALL_SUB_DEVICE(DeviceManagerClient *handle, cJSON *root);

// ------------------------ ESP-NOW 回调 ------------------------
// 发送回调
void on_data_sent(const uint8_t *mac_addr, esp_now_send_status_t status)
{
     ESP_LOGI(TAG, "Send status: %s", status == ESP_NOW_SEND_SUCCESS ? "Success" : "Fail");
}

// 接收回调
void on_data_recv(const esp_now_recv_info_t *recv_info, const uint8_t *data, int len)
{
     extern ManageModule *manageModule;
     DeviceManagerClient *handle = manageModule->deviceManagerClient;
     if (!handle)
     {
          ESP_LOGE(TAG, "No DeviceManagerClient available");
          return;
     }
     if (memcmp(recv_info->src_addr, handle->self_mac, 6) == 0)
          return;

     uint8_t peerAddress[6];
     memcpy(peerAddress, recv_info->src_addr, 6);

     if (!esp_now_is_peer_exist(peerAddress))
     {
          add_broadcast_peer(handle, peerAddress);
          ESP_LOGW(TAG, "Peer registered");
     }

     char *json_buf = malloc(len + 1);
     if (!json_buf)
     {
          ESP_LOGE(TAG, "Failed to allocate memory for received data");
          return;
     }
     memcpy(json_buf, data, len);
     json_buf[len] = '\0';

     ESP_LOGI(TAG, "Received from %02X:%02X:%02X:%02X:%02X:%02X -> %.*s",
              recv_info->src_addr[0], recv_info->src_addr[1], recv_info->src_addr[2],
              recv_info->src_addr[3], recv_info->src_addr[4], recv_info->src_addr[5],
              len, (char *)data);

     cJSON *root = cJSON_Parse(json_buf);
     if (!root)
     {
          free(json_buf);
          cJSON_Delete(root);
          ESP_LOGE(TAG, "Failed to parse JSON");
          return;
     }

     DeviceType deviceType = cjson_get_int(root, "sendDeviceType");
     if (deviceType != DEVICE_TYPE_SERVICE)
     {
          free(json_buf);
          cJSON_Delete(root);
          // 子设备只接收 服务端或特定设备的西消息
          return;
     }

     int messageType = cjson_get_int(root, "messageType");
     const char *msgId = cjson_get_str(root, "msgId");
     if (messageType == ASK_DEVICE_INFO)
     {
          handle_ASK_DEVICE_INFO(handle, peerAddress, msgId);
     }
     else if (messageType == BROADCAST_NET_INFO)
     {
          handle_BROADCAST_NET_INFO(handle, root);
     }
     else if (messageType == BROADCAST_ALL_SUB_DEVICE)
     {
          handle_BROADCAST_ALL_SUB_DEVICE(handle, root);
     }
     free(json_buf);
     cJSON_Delete(root);
}

// 添加广播信道
void add_broadcast_peer(DeviceManagerClient *handle, uint8_t peerAddress[])
{
     // 获取当前 STA 的信道
     uint8_t primary_channel = 0;
     wifi_second_chan_t second;
     esp_wifi_get_channel(&primary_channel, &second);

     esp_now_peer_info_t broadcastPeer = {0};
     memcpy(broadcastPeer.peer_addr, peerAddress, 6);
     broadcastPeer.channel = primary_channel;
     broadcastPeer.ifidx = WIFI_IF_STA;
     broadcastPeer.encrypt = false;

     esp_err_t status = esp_now_add_peer(&broadcastPeer);
     if (status != ESP_OK && status != ESP_ERR_ESPNOW_EXIST)
     {
          ESP_LOGE(TAG, "Failed to add broadcast peer: %s", esp_err_to_name(status));
     }
     else
     {
          ESP_LOGI(TAG, "Broadcast peer added successfully on channel %d", primary_channel);
     }
}

// 子设备回复服务端询问，上传设备信息
void handle_ASK_DEVICE_INFO(DeviceManagerClient *handle, uint8_t peerAddress[6], const char *msgId)
{
     cJSON *root = cJSON_CreateObject();
     if (!root)
          return;

     cJSON_AddNumberToObject(root, "sendDeviceType", CURRENT_DEVICE_TYPE);
     cJSON_AddStringToObject(root, "sendDeviceTypeDes", DeviceTypeDesList[CURRENT_DEVICE_TYPE]);
     cJSON_AddNumberToObject(root, "messageType", RESPONSE_ASK_DEVICE_INFO);
     cJSON_AddStringToObject(root, "messageTypeDes", MessageTypeDesList[RESPONSE_ASK_DEVICE_INFO]);
     cJSON_AddStringToObject(root, "msgId", msgId ? msgId : "");

     cJSON *data = cJSON_CreateObject();
     if (!data)
     {
          cJSON_Delete(root);
          return;
     }

     char macStr[18];
     snprintf(macStr, sizeof(macStr), "%02X:%02X:%02X:%02X:%02X:%02X",
              handle->self_mac[0], handle->self_mac[1], handle->self_mac[2],
              handle->self_mac[3], handle->self_mac[4], handle->self_mac[5]);

     cJSON_AddStringToObject(data, "macAddress", macStr);
     cJSON_AddNumberToObject(data, "deviceType", CURRENT_DEVICE_TYPE);
     cJSON_AddStringToObject(data, "deviceTypeDes", DeviceTypeDesList[CURRENT_DEVICE_TYPE]);
     cJSON_AddItemToObject(root, "data", data);

     char *json_str = cJSON_PrintUnformatted(root);
     if (!json_str)
     {
          cJSON_Delete(root);
          return;
     }

     ESP_LOGI(TAG, "Replying with JSON: %s", json_str);

     esp_err_t result = esp_now_send(peerAddress, (uint8_t *)json_str, strlen(json_str));
     if (result != ESP_OK)
     {
          ESP_LOGE(TAG, "Error sending message: %s", esp_err_to_name(result));
     }

     cJSON_Delete(root);
     free(json_str);
}

/// 子设备询问网络配置
void sub_device_ASK_NET_INFO(DeviceManagerClient *handle, uint8_t peerAddress[6])
{
     cJSON *root = cJSON_CreateObject();
     if (!root)
          return;

     cJSON_AddNumberToObject(root, "sendDeviceType", CURRENT_DEVICE_TYPE);
     cJSON_AddStringToObject(root, "sendDeviceTypeDes", DeviceTypeDesList[CURRENT_DEVICE_TYPE]);
     cJSON_AddNumberToObject(root, "messageType", SUB_DEVICE_ASK_NET_INFO);
     cJSON_AddStringToObject(root, "messageTypeDes", MessageTypeDesList[SUB_DEVICE_ASK_NET_INFO]);

     cJSON *data = cJSON_CreateObject();
     if (!data)
     {
          cJSON_Delete(root);
          return;
     }

     char *json_str = cJSON_PrintUnformatted(root);
     if (!json_str)
     {
          cJSON_Delete(root);
          return;
     }

     ESP_LOGI(TAG, "RequestNetConfig with JSON: %s", json_str);

     esp_err_t result = esp_now_send(peerAddress, (uint8_t *)json_str, strlen(json_str));
     if (result != ESP_OK)
     {
          ESP_LOGE(TAG, "Error sending message: %s", esp_err_to_name(result));
     }

     cJSON_Delete(root);
     free(json_str);
}

// 子设备接收服务端网络配置信息
void handle_BROADCAST_NET_INFO(DeviceManagerClient *handle, cJSON *root)
{
     cJSON *dataObj = cJSON_GetObjectItem(root, "data");
     if (!cJSON_IsObject(dataObj))
          return;
     const char *ssid = cjson_get_str(dataObj, "ssid");
     const char *password = cjson_get_str(dataObj, "password");
     const NetConnectType netConnectType = cjson_get_int(dataObj, "netConnectType");
     const char *mqttAccount = cjson_get_str(dataObj, "mqttAccount");
     const char *mqttPassword = cjson_get_str(dataObj, "mqttPassword");
     const char *mqttIP = cjson_get_str(dataObj, "mqttIP");
     int mqttPort = cjson_get_int(dataObj, "mqttPort");
     const char *mqttSubTopic = cjson_get_str(dataObj, "mqttSubTopic");
     const char *mqttReceiveId = cjson_get_str(dataObj, "mqttReceiveId");
     const char *sipUri = cjson_get_str(dataObj, "sipUri");

     NetConfig *netConfig = calloc(1, sizeof(NetConfig)); // heap
     if (!netConfig)
     {
          ESP_LOGE(TAG, "calloc failed");
          cJSON_Delete(root);
          return;
     }

     if (strlen(ssid) > 0 && strlen(password) > 0)
     {
          WiFiConfig wifiConfig = {0};
          strncpy(wifiConfig.ssid, ssid, sizeof(wifiConfig.ssid) - 1);
          strncpy(wifiConfig.password, password, sizeof(wifiConfig.password) - 1);
          wifiConfig.netConnectType = netConnectType;
          wifiConfig.ssid[sizeof(wifiConfig.ssid) - 1] = '\0';
          wifiConfig.password[sizeof(wifiConfig.password) - 1] = '\0';
          handle->netConfig.wifiConfig = wifiConfig;
          ESP_LOGI(TAG, "Receive wifiConfig:");
          ESP_LOGI(TAG, "  ssid: %s", handle->netConfig.wifiConfig.ssid);                     // wifi名称
          ESP_LOGI(TAG, "  password: %s", handle->netConfig.wifiConfig.password);             // wifi密码
          ESP_LOGI(TAG, "  netConnectType: %d", handle->netConfig.wifiConfig.netConnectType); // wifi密码
     }

     if (strlen(mqttAccount) > 0 && strlen(mqttPassword) > 0 &&
         strlen(mqttIP) > 0 && strlen(mqttSubTopic) > 0 &&
         strlen(mqttReceiveId) > 0 && mqttPort != 0)
     {
          strncpy(handle->netConfig.mqttAccount, mqttAccount, sizeof(handle->netConfig.mqttAccount) - 1);
          strncpy(handle->netConfig.mqttPassword, mqttPassword, sizeof(handle->netConfig.mqttPassword) - 1);
          strncpy(handle->netConfig.mqttIP, mqttIP, sizeof(handle->netConfig.mqttIP) - 1);
          strncpy(handle->netConfig.mqttSubTopic, mqttSubTopic, sizeof(handle->netConfig.mqttSubTopic) - 1);
          strncpy(handle->netConfig.mqttReceiveId, mqttReceiveId, sizeof(handle->netConfig.mqttReceiveId) - 1);
          handle->netConfig.mqttPort = mqttPort;

          handle->netConfig.mqttAccount[sizeof(handle->netConfig.mqttAccount) - 1] = '\0';
          handle->netConfig.mqttPassword[sizeof(handle->netConfig.mqttPassword) - 1] = '\0';
          handle->netConfig.mqttIP[sizeof(handle->netConfig.mqttIP) - 1] = '\0';
          handle->netConfig.mqttSubTopic[sizeof(handle->netConfig.mqttSubTopic) - 1] = '\0';
          handle->netConfig.mqttReceiveId[sizeof(handle->netConfig.mqttReceiveId) - 1] = '\0';

          ESP_LOGI(TAG, "Receive netConfig:");
          ESP_LOGI(TAG, "  mqttAccount: %s", handle->netConfig.mqttAccount);   // mqtt的用户名
          ESP_LOGI(TAG, "  mqttPassword: %s", handle->netConfig.mqttPassword); // mqtt的密码
          ESP_LOGI(TAG, "  mqttIP: %s", handle->netConfig.mqttIP);             // mqtt服务器的IP地址 如192.168.43.52
          ESP_LOGI(TAG, "  mqttPort: %d", handle->netConfig.mqttPort);
          ESP_LOGI(TAG, "  mqttSubTopic: %s", handle->netConfig.mqttSubTopic);
          ESP_LOGI(TAG, "  mqttReceiveId: %s", handle->netConfig.mqttReceiveId);
     }
     if (strlen(sipUri) > 0)
     {
          strncpy(handle->netConfig.sipUri, sipUri, sizeof(handle->netConfig.sipUri) - 1);
          handle->netConfig.sipUri[sizeof(handle->netConfig.sipUri) - 1] = '\0';
          ESP_LOGI(TAG, "Receive sipUri:");
          ESP_LOGI(TAG, "  sipUri: %s", handle->netConfig.sipUri); // sip服务器的uri，如udp://1004:1234@192.168.1.8:5060
     }

     if (handle->recv_net_config_event_callback_t)
     {
          handle->recv_net_config_event_callback_t(handle->netConfig);
     }
}

// 子设备接收到服务端广播的设备列表
void handle_BROADCAST_ALL_SUB_DEVICE(DeviceManagerClient *handle, cJSON *root)
{
     cJSON *dataObj = cJSON_GetObjectItem(root, "data");
     if (!cJSON_IsObject(dataObj))
          return;
}

// 主动上报自身信息 和询问网络配置
void ask_config_info_when_start_task(void *arg)
{
     DeviceManagerClient *handle = (DeviceManagerClient *)arg;
     vTaskDelay(pdMS_TO_TICKS(1000));
     handle_ASK_DEVICE_INFO(handle, handle->broadcastAddress, "");
     while (1)
     {
          bool netInfoIsNil = handle->netConfig.wifiConfig.ssid[0] == '\0';
          if (netInfoIsNil)
          {
               // 询问网络配置
               sub_device_ASK_NET_INFO(handle, handle->broadcastAddress);
               // 任意一个配置未获取，间隔5秒重新获取
               vTaskDelay(pdMS_TO_TICKS(5000));
          }
          else
          {
               // 已存在了信息，就挂起
               vTaskSuspend(NULL);
          }
     }
}

// 创建管理器
DeviceManagerClient *manager_init()
{
     DeviceManagerClient *handle = calloc(1, sizeof(struct DeviceManagerClient));
     if (!handle)
          return NULL;
     memset(handle, 0, sizeof(struct DeviceManagerClient));
     uint8_t bcast[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
     memcpy(handle->broadcastAddress, bcast, 6);

     uint8_t mac[6];
     esp_wifi_get_mac(WIFI_IF_STA, mac); // 获取本机 MAC
     memcpy(handle->self_mac, mac, 6);

     // 初始化 ESP-NOW
     ESP_ERROR_CHECK(esp_now_init());
     ESP_ERROR_CHECK(esp_now_register_send_cb(on_data_sent));
     ESP_ERROR_CHECK(esp_now_register_recv_cb(on_data_recv));

     add_broadcast_peer(handle, bcast);
     xTaskCreatePinnedToCore(ask_config_info_when_start_task, "ask_config_info_when_start_task", 1024 * 10, handle, 2, &handle->ask_info_when_start_task_handle, 0);
     return handle;
}

// 销毁管理器
void destroy(DeviceManagerClient *handle)
{
     if (handle)
          free(handle);
}
